package igloo.ui;

import igloo.Application;
import igloo.aws.Region;
import igloo.controller.ArchiveController;
import igloo.controller.IglooController;
import igloo.controller.VaultController;
import igloo.model.Archive;
import igloo.model.Vault;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileSystemView;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;

import net.miginfocom.swing.MigLayout;

import org.jdesktop.swingx.JXTitledPanel;

import com.l2fprod.common.swing.JOutlookBar;

public class IglooPanel extends JPanel
{
    private static final long serialVersionUID = 1L;
    private final ImageIcon VAULT_IMAGE = new ImageIcon("images/safe.png");
    private final ImageIcon ARCHIVE_IMAGE = new ImageIcon("images/box.png");

    private final IglooController mIglooController;

    private JMenuBar mMenuBar;
    private JMenu mFileMenu;
    private JMenu mHelpMenu;

    private JSplitPane mHorizontalSplitPane;
    private JOutlookBar mOutlookBar;
    private JXTitledPanel mVaultPanel;
    private JToolBar mVaultToolBar;
    private JButton mCreateVaultButton;
    private JButton mRemoveVaultButton;
    private JTable mUSEast1Table;
    private JTable mUSWest1Table;
    private JTable mUSWest2Table;
    private JTable mEUTable;
    private JTable mAPTable;

    private JSplitPane mVerticalSplitPane;
    private JXTitledPanel mArchiveTitledPanel;
    private JToolBar mArchiveToolBar;
    private JButton mAddArchiveButton;
    private JButton mRemoveArchiveButton;
    private JButton mRefreshButton;
    private JTable mArchiveTable;

    private JXTitledPanel mJobsTitledPanel;

    private ArchiveTableModel mArchiveTableModel = new ArchiveTableModel();

    public IglooPanel(IglooController iglooController)
    {
        mIglooController = iglooController;

        // setJMenuBar(getIglooMenuBar());

        setLayout(new MigLayout("fill, insets 0 0 0 0", "[][grow]", ""));
        add(getVaultPanel(), "w 250!, growy");
        add(getVerticalSplitPane(), "grow");
        // add(getHorizontalSplitPane(), BorderLayout.CENTER);
    }

    private JSplitPane getHorizontalSplitPane()
    {
        if(mHorizontalSplitPane == null)
        {
            mHorizontalSplitPane = new JSplitPane();
            mHorizontalSplitPane.setLeftComponent(getVaultPanel());
            mHorizontalSplitPane.setRightComponent(getVerticalSplitPane());
            mHorizontalSplitPane.setContinuousLayout(true);
            mHorizontalSplitPane.setDividerLocation(0.15);
            // mHorizontalSplitPane.setResizeWeight(0.2);
        }

        return mHorizontalSplitPane;
    }

    private JMenuBar getIglooMenuBar()
    {
        if(mMenuBar == null)
        {
            mMenuBar = new JMenuBar();
            mMenuBar.add(getFileMenu());
            mMenuBar.add(getHelpMenu());
        }

        return mMenuBar;
    }

    private JMenu getFileMenu()
    {
        if(mFileMenu == null)
        {
            mFileMenu = new JMenu("File");

            JMenu newMenu = new JMenu("New");
            JMenuItem newVaultMenuItem = new JMenuItem("Vault...");
            JMenuItem newArchiveMenuItem = new JMenuItem("Archive...");
            newMenu.add(newVaultMenuItem);
            newMenu.add(newArchiveMenuItem);

            mFileMenu.add(newMenu);

            mFileMenu.addSeparator();

            JMenuItem exitMenuItem = new JMenuItem("Exit");
            mFileMenu.add(exitMenuItem);

        }
        return mFileMenu;
    }

    private JMenu getHelpMenu()
    {
        if(mHelpMenu == null)
        {
            mHelpMenu = new JMenu("Help");

            JMenuItem aboutMenuItem = new JMenuItem("About");
            mHelpMenu.add(aboutMenuItem);
        }

        return mHelpMenu;
    }

    private JXTitledPanel getVaultPanel()
    {
        if(mVaultPanel == null)
        {
            mVaultPanel = new JXTitledPanel("Vaults", getOutlookBar());
            mVaultPanel.setRightDecoration(getVaultToolBar());
        }

        return mVaultPanel;
    }

    private JOutlookBar getOutlookBar()
    {
        if(mOutlookBar == null)
        {
            mOutlookBar = new JOutlookBar();

            JScrollPane sp1 = new JScrollPane(getUSEast1Table());
            sp1.setBorder(BorderFactory.createEmptyBorder());
            mOutlookBar.addTab("US East (VA)", sp1);

            JScrollPane sp2 = new JScrollPane(getUSWest1Table());
            sp2.setBorder(BorderFactory.createEmptyBorder());
            mOutlookBar.addTab("US West (CA)", sp2);

            JScrollPane sp3 = new JScrollPane(getUSWest2Table());
            sp3.setBorder(BorderFactory.createEmptyBorder());
            mOutlookBar.addTab("US West (OR)", sp3);

            JScrollPane sp4 = new JScrollPane(getEUTable());
            sp4.setBorder(BorderFactory.createEmptyBorder());
            mOutlookBar.addTab("EU (Ireland)", sp4);

            JScrollPane sp5 = new JScrollPane(getAPTable());
            sp5.setBorder(BorderFactory.createEmptyBorder());
            mOutlookBar.addTab("Asia Pacific (Tokyo)", sp5);
        }

        return mOutlookBar;
    }

    private JToolBar getVaultToolBar()
    {
        if(mVaultToolBar == null)
        {
            mVaultToolBar = new JToolBar();
            mVaultToolBar.setOpaque(false);
            mVaultToolBar.setFloatable(false);
            mVaultToolBar.setBorderPainted(false);

            mVaultToolBar.add(getCreateVaultButton());
            mVaultToolBar.add(getRemoveVaultButtonPanel());
        }

        return mVaultToolBar;
    }

    private JButton getCreateVaultButton()
    {
        if(mCreateVaultButton == null)
        {
            mCreateVaultButton = new JButton(new ImageIcon("images/safe_add.png"));
            mCreateVaultButton.setOpaque(false);
            mCreateVaultButton.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
            mCreateVaultButton.setToolTipText("Create a vault.");

            mCreateVaultButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e)
                {
                    Region region = null;
                    int selIndex = getOutlookBar().getSelectedIndex();
                    switch(selIndex)
                    {
                        case 0:
                            region = Region.US_EAST_1;
                        break;

                        case 1:
                            region = Region.US_WEST_1;
                        break;

                        case 2:
                            region = Region.US_WEST_2;
                        break;

                        case 3:
                            region = Region.EU;
                        break;

                        case 4:
                            region = Region.ASIA;
                        break;
                    }

                    CreateVaultDialog dlg = new CreateVaultDialog(Application.getInstance()
                                                                             .getFrame(), true,
                                                                  mIglooController, region);
                    dlg.pack();
                    dlg.setLocationRelativeTo(getVaultPanel());
                    dlg.setVisible(true);

                    // String name = dlg.getVaultName();
                    // Region region = dlg.getRegion();

                    // TODO: Create vault
                }
            });
        }

        return mCreateVaultButton;
    }

    private JButton getRemoveVaultButtonPanel()
    {
        if(mRemoveVaultButton == null)
        {
            mRemoveVaultButton = new JButton(new ImageIcon("images/safe_remove.png"));
            mRemoveVaultButton.setOpaque(false);
            mRemoveVaultButton.setToolTipText("Delete the selected vault.");
            mRemoveVaultButton.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));

            mRemoveVaultButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e)
                {
                }
            });
        }

        return mRemoveVaultButton;
    }

    @SuppressWarnings("serial")
    private JTable getUSEast1Table()
    {
        if(mUSEast1Table == null)
        {
            mUSEast1Table = new JTable(new VaultTableModel(mIglooController.getIgloo(),
                                                           Region.US_EAST_1)) {
                @Override
                public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
                {
                    if(column == 0)
                    {
                        if(renderer instanceof DefaultTableCellRenderer)
                            ((DefaultTableCellRenderer)renderer).setIcon(VAULT_IMAGE);
                    }

                    return super.prepareRenderer(renderer, row, column);
                }
            };
            mUSEast1Table.setFillsViewportHeight(true);
            mUSEast1Table.setTableHeader(null);
            mUSEast1Table.setShowGrid(false);

            mUSEast1Table.getColumnModel().getColumn(0).setPreferredWidth(20);
        }

        return mUSEast1Table;
    }

    @SuppressWarnings("serial")
    private JTable getUSWest1Table()
    {
        if(mUSWest1Table == null)
        {
            mUSWest1Table = new JTable(new VaultTableModel(mIglooController.getIgloo(),
                                                           Region.US_WEST_1)) {
                @Override
                public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
                {
                    if(column == 0)
                    {
                        if(renderer instanceof DefaultTableCellRenderer)
                            ((DefaultTableCellRenderer)renderer).setIcon(VAULT_IMAGE);
                    }

                    return super.prepareRenderer(renderer, row, column);
                }
            };
            mUSWest1Table.setFillsViewportHeight(true);
            mUSWest1Table.setTableHeader(null);
            mUSWest1Table.setShowGrid(false);
        }

        return mUSWest1Table;
    }

    @SuppressWarnings("serial")
    private JTable getUSWest2Table()
    {
        if(mUSWest2Table == null)
        {
            mUSWest2Table = new JTable(new VaultTableModel(mIglooController.getIgloo(),
                                                           Region.US_WEST_2)) {
                @Override
                public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
                {
                    if(column == 0)
                    {
                        if(renderer instanceof DefaultTableCellRenderer)
                            ((DefaultTableCellRenderer)renderer).setIcon(VAULT_IMAGE);
                    }

                    return super.prepareRenderer(renderer, row, column);
                }
            };
            mUSWest2Table.setFillsViewportHeight(true);
            mUSWest2Table.setTableHeader(null);
            mUSWest2Table.setShowGrid(false);
        }

        return mUSWest2Table;
    }

    @SuppressWarnings("serial")
    private JTable getEUTable()
    {
        if(mEUTable == null)
        {
            mEUTable = new JTable(new VaultTableModel(mIglooController.getIgloo(), Region.EU)) {
                @Override
                public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
                {
                    if(column == 0)
                    {
                        if(renderer instanceof DefaultTableCellRenderer)
                            ((DefaultTableCellRenderer)renderer).setIcon(VAULT_IMAGE);
                    }

                    return super.prepareRenderer(renderer, row, column);
                }
            };
            mEUTable.setFillsViewportHeight(true);
            mEUTable.setTableHeader(null);
            mEUTable.setShowGrid(false);
        }

        return mEUTable;
    }

    @SuppressWarnings("serial")
    private JTable getAPTable()
    {
        if(mAPTable == null)
        {
            mAPTable = new JTable(new VaultTableModel(mIglooController.getIgloo(), Region.ASIA)) {
                @Override
                public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
                {
                    if(column == 0)
                    {
                        if(renderer instanceof DefaultTableCellRenderer)
                            ((DefaultTableCellRenderer)renderer).setIcon(VAULT_IMAGE);
                    }

                    return super.prepareRenderer(renderer, row, column);
                }
            };
            mAPTable.setFillsViewportHeight(true);
            mAPTable.setTableHeader(null);
            mAPTable.setShowGrid(false);
        }

        return mAPTable;
    }

    private JSplitPane getVerticalSplitPane()
    {
        if(mVerticalSplitPane == null)
        {
            mVerticalSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
            mVerticalSplitPane.setTopComponent(getArchiveTitledPanel());
            mVerticalSplitPane.setBottomComponent(getJobsTitledPanel());
            mVerticalSplitPane.setOneTouchExpandable(true);
            mVerticalSplitPane.setDividerLocation(0.75);
            mVerticalSplitPane.setResizeWeight(0.85);
        }

        return mVerticalSplitPane;
    }

    private JXTitledPanel getArchiveTitledPanel()
    {
        if(mArchiveTitledPanel == null)
        {
            mArchiveTitledPanel = new JXTitledPanel("Archives");
            mArchiveTitledPanel.setRightDecoration(getArchiveToolbar());

            JScrollPane scrollPane = new JScrollPane(getArchiveTable());
            scrollPane.setBorder(BorderFactory.createEmptyBorder());
            mArchiveTitledPanel.add(scrollPane);
        }

        return mArchiveTitledPanel;
    }

    private JToolBar getArchiveToolbar()
    {
        if(mArchiveToolBar == null)
        {
            mArchiveToolBar = new JToolBar();
            mArchiveToolBar.setFloatable(false);
            mArchiveToolBar.setOpaque(false);
            mArchiveToolBar.setBorderPainted(false);

            mArchiveToolBar.add(getAddArchiveButton());
            mArchiveToolBar.add(getRemoveArchiveButton());
            // mArchiveToolBar.add(getRefreshButton());
        }

        return mArchiveToolBar;
    }

    private JButton getAddArchiveButton()
    {
        if(mAddArchiveButton == null)
        {
            mAddArchiveButton = new JButton(new ImageIcon("images/box_add.png"));
            mAddArchiveButton.setEnabled(false);
            mAddArchiveButton.setOpaque(false);
            mAddArchiveButton.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
            mAddArchiveButton.setMinimumSize(new Dimension(20, 20));

            mAddArchiveButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e)
                {
                    int sel = getOutlookBar().getSelectedIndex();
                    JTable table = getTable(sel);
                    Vault vault = ((VaultTableModel)table.getModel()).getVaultAt(table.getSelectedRow());
                    VaultController controller = mIglooController.getVaultController(vault);
                    UploadArchiveDialog dlg = new UploadArchiveDialog(Application.getInstance()
                                                                                 .getFrame(), true,
                                                                      controller);
                    dlg.pack();
                    dlg.setLocationRelativeTo(getArchiveTitledPanel());
                    dlg.setVisible(true);
                }
            });

            final ListSelectionListener selectionListener = new ListSelectionListener() {
                @Override
                public void valueChanged(ListSelectionEvent e)
                {
                    int sel = e.getFirstIndex();
                    mAddArchiveButton.setEnabled(sel != -1);
                }
            };

            JTable table = getTable(getOutlookBar().getSelectedIndex());
            if(table != null)
            {
                table.getSelectionModel().addListSelectionListener(selectionListener);
            }

            getOutlookBar().addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e)
                {
                    JTable table;
                    for(int i = 0; i < getOutlookBar().getTabCount(); ++i)
                    {
                        table = getTable(i);
                        table.getSelectionModel().removeListSelectionListener(selectionListener);
                    }

                    int sel = getOutlookBar().getSelectedIndex();
                    if(sel != -1)
                    {
                        table = getTable(sel);
                        table.getSelectionModel().addListSelectionListener(selectionListener);

                        mAddArchiveButton.setEnabled(table.getSelectedRow() != -1);
                    }
                    else
                        mAddArchiveButton.setEnabled(false);
                }
            });

        }

        return mAddArchiveButton;
    }

    private JButton getRemoveArchiveButton()
    {
        if(mRemoveArchiveButton == null)
        {
            mRemoveArchiveButton = new JButton(new ImageIcon("images/box_remove.png"));
            mRemoveArchiveButton.setEnabled(false);
            mRemoveArchiveButton.setOpaque(false);
            mRemoveArchiveButton.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
            mRemoveArchiveButton.setMinimumSize(new Dimension(20, 20));
            mRemoveArchiveButton.setToolTipText("Delete selected archive");

            mRemoveArchiveButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e)
                {
                    int sel = getArchiveTable().getSelectedRow();
                    if(sel != -1)
                    {
                        Archive archive = mArchiveTableModel.getArchiveAt(sel);
                        int option = JOptionPane.showConfirmDialog(IglooPanel.this,
                                                                   "Are you sure you want to delete the selected archive?\n\n"
                                                                           + archive.getName()
                                                                           + "\n" + archive.getId(),
                                                                   "Delete Archive",
                                                                   JOptionPane.YES_NO_OPTION);
                        if(option == JOptionPane.YES_OPTION)
                        {
                            Vault vault = archive.getVault();
                            VaultController vaultController = mIglooController.getVaultController(vault);
                            vaultController.deleteArchive(archive);
                        }
                    }
                }
            });

            getArchiveTable().getSelectionModel()
                             .addListSelectionListener(new ListSelectionListener() {
                                 @Override
                                 public void valueChanged(ListSelectionEvent e)
                                 {
                                     int selCount = getArchiveTable().getSelectedRowCount();
                                     mRemoveArchiveButton.setEnabled(selCount > 0);
                                 }
                             });
        }

        return mRemoveArchiveButton;
    }

    private JButton getRefreshButton()
    {
        if(mRefreshButton == null)
        {
            mRefreshButton = new JButton("Refresh");

            mRefreshButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e)
                {
                }
            });
        }

        return mRefreshButton;
    }

    @SuppressWarnings("serial")
    private JTable getArchiveTable()
    {
        if(mArchiveTable == null)
        {
            mArchiveTable = new JTable(mArchiveTableModel) {
                @Override
                public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
                {
                    if(column == 0)
                    {
                        if(renderer instanceof DefaultTableCellRenderer)
                        {
                            FileSystemView view = FileSystemView.getFileSystemView();
                            Archive archive = mArchiveTableModel.getArchiveAt(row);
                            Icon icon = view.getSystemIcon(new File(archive.getPath()));
                            ((DefaultTableCellRenderer)renderer).setIcon((icon != null) ? icon
                                    : ARCHIVE_IMAGE);
                        }
                    }
                    else
                    {
                        if(renderer instanceof DefaultTableCellRenderer)
                        {
                            ((DefaultTableCellRenderer)renderer).setIcon(null);
                        }
                    }

                    return super.prepareRenderer(renderer, row, column);
                }
            };
            mArchiveTable.setFillsViewportHeight(true);

            mArchiveTable.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e)
                {
                    if(e.getClickCount() >= 2)
                    {
                        int sel = mArchiveTable.getSelectedRow();
                        if(sel != -1)
                        {
                            Archive archive = mArchiveTableModel.getArchiveAt(sel);
                            Vault vault = archive.getVault();
                            VaultController vaultController = mIglooController.getVaultController(vault);
                            ArchiveController archiveController = vaultController.getArchiveController(archive);

                        }
                    }
                }
            });

            getUSEast1Table().getSelectionModel()
                             .addListSelectionListener(new ListSelectionListener() {
                                 @Override
                                 public void valueChanged(ListSelectionEvent e)
                                 {
                                     Vault vault = null;

                                     int index = getUSEast1Table().getSelectedRow();
                                     if(index != -1)
                                     {
                                         vault = ((VaultTableModel)getUSEast1Table().getModel()).getVaultAt(index);
                                     }

                                     mArchiveTableModel.setVault(vault);
                                 }
                             });

            getUSWest1Table().getSelectionModel()
                             .addListSelectionListener(new ListSelectionListener() {
                                 @Override
                                 public void valueChanged(ListSelectionEvent e)
                                 {
                                     Vault vault = null;

                                     int index = getUSWest1Table().getSelectedRow();
                                     if(index != -1)
                                     {
                                         vault = ((VaultTableModel)getUSWest1Table().getModel()).getVaultAt(index);
                                     }

                                     mArchiveTableModel.setVault(vault);
                                 }
                             });

            getUSWest2Table().getSelectionModel()
                             .addListSelectionListener(new ListSelectionListener() {
                                 @Override
                                 public void valueChanged(ListSelectionEvent e)
                                 {
                                     Vault vault = null;

                                     int index = getUSWest2Table().getSelectedRow();
                                     if(index != -1)
                                     {
                                         vault = ((VaultTableModel)getUSWest2Table().getModel()).getVaultAt(index);
                                     }

                                     mArchiveTableModel.setVault(vault);
                                 }
                             });

            getEUTable().getSelectionModel().addListSelectionListener(new ListSelectionListener() {
                @Override
                public void valueChanged(ListSelectionEvent e)
                {
                    Vault vault = null;

                    int index = getEUTable().getSelectedRow();
                    if(index != -1)
                    {
                        vault = ((VaultTableModel)getEUTable().getModel()).getVaultAt(index);
                    }

                    mArchiveTableModel.setVault(vault);
                }
            });

            getAPTable().getSelectionModel().addListSelectionListener(new ListSelectionListener() {
                @Override
                public void valueChanged(ListSelectionEvent e)
                {
                    Vault vault = null;

                    int index = getAPTable().getSelectedRow();
                    if(index != -1)
                    {
                        vault = ((VaultTableModel)getAPTable().getModel()).getVaultAt(index);
                    }

                    mArchiveTableModel.setVault(vault);
                }
            });
        }

        return mArchiveTable;
    }

    private JXTitledPanel getJobsTitledPanel()
    {
        if(mJobsTitledPanel == null)
        {
            mJobsTitledPanel = new JXTitledPanel("Jobs");

            JScrollPane scrollPane = new JScrollPane(new JTable());
            scrollPane.setBorder(BorderFactory.createEmptyBorder());
            mJobsTitledPanel.add(scrollPane);
        }

        return mJobsTitledPanel;
    }

    private JTable getTable(int index)
    {
        switch(index)
        {
            case 0:
                return getUSEast1Table();
            case 1:
                return getUSWest1Table();
            case 2:
                return getUSWest2Table();
            case 3:
                return getEUTable();
            case 4:
                return getAPTable();
        }

        return null;
    }

    public static void main(String[] args) throws Exception
    {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        IglooPanel panel = new IglooPanel(new IglooController(null));
        frame.setContentPane(panel);

        frame.setVisible(true);
    }
}
